package com.yy.micro.magic.core.result;

import com.yy.micro.magic.core.result.name.NameStrategy;
import com.yy.micro.magic.core.result.value.ValuePair;
import com.yy.micro.magic.core.result.value.ValueStrategy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public interface ResultStrategy<T> {

    T applay(T t);

    void setValueStrategies(List<ValueStrategy> strategies);

    void setNameStrategy(NameStrategy strategy);

    class NameValueResultStrategy implements  ResultStrategy<Map<String,Object>>{

        private Logger logger = LoggerFactory.getLogger(getClass());
        private NameStrategy strategy;

        private List<ValueStrategy> strategies;

        @Override
        public void setNameStrategy(final NameStrategy strategy) {
            this.strategy = strategy;
        }

        @Override
        public void setValueStrategies(final List<ValueStrategy> strategies) {
            this.strategies = strategies;
        }

        @Override
        public Map<String, Object> applay(final Map<String, Object> src) {
            if (null == strategy && null ==strategies){
                return src;
            }
            return traverseMap(src);
        }

        public static NameValueResultStrategy create(List<ValueStrategy> strategies,NameStrategy nameStrategy){
            NameValueResultStrategy strategy = new NameValueResultStrategy();
            strategy.setNameStrategy(nameStrategy);
            strategy.setValueStrategies(strategies);
            return strategy;
        }

        private boolean include(String key ,Object value,Map<String,Object> parent){
            boolean rel = true;
            if (null != strategies){
                ValuePair pair = ValuePair.create(key,value,parent);
                pair.setStrategy(strategy);
                for (ValueStrategy s :strategies){
                    rel &= s.include(pair);
                }
            }
            return rel;
        }
        /**
         * 遍历Map，筛选出甩的value不为空的节点
         *
         * @param map
         * @return
         */
        private Map<String, Object> traverseMap(final Map<String, Object> map) {
            final Map<String, Object> result = new HashMap<String, Object>();
            map.forEach((k,v)->{
                if (v instanceof  Map){
                    result.put(k,traverseMap((Map<String,Object>)v));
                }else if (v instanceof List){
                    List<Object> list =traverseList( k, (List<Object>) v);
                    if (include(k,list,result)){
                        k = getOutKay(k);
                        if (!result.containsKey(k)){
                            result.put(k,list);
                        }else{
                            logger.info("Result contain key "+k);
                        }
                    }
                }else{
                    if (include(k,v,result)){
                        k = getOutKay(k);
                        if (!result.containsKey(k)){
                            result.put(k,v);
                        }else {
                            logger.info("Result contain key "+k);
                        }
                    }
                }
            });

            return result;
        }

        private List<Object> traverseList( final String k, final List<Object> v) {
            List<Object> list = v;
            List<Object> listValue = new ArrayList<>();
            list.forEach(o->{
                if (o instanceof Map){
                    listValue.add(traverseMap((Map<String, Object>) o));
                }else if (o instanceof  List){
                    listValue.add(traverseList(k, (List<Object>) o));
                }else{
                    listValue.add(o);
                }
            });
            return listValue;
        }

        /**
         * 输出key的模式，首字母大写，全小写，全大写，保持不变
         *
         * @param key
         * @return
         */
        private String getOutKay(final String key) {
            if (null != strategy){
                return strategy.format(key);
            }
            return key;
        }

        /**
         * 遍历对象，特别处理Map和List，遇到这种集合，需要遍历其所有元素。采用后续遍历方式，便于清理list为empty的内容
         *
         * @param obj
         * @return
         */
//        private Object traverseObject(String key,final Object obj,Map<String,Object> parent) {
//            Object result = null;
//            if (obj instanceof Map) {// 遍历Map中所有元素，筛选出所有value不为null的元素
//                return  traverseMap((Map<String, Object>) obj);
//            } else if (obj instanceof List) {// 同Map
//                final List<Object> l = traverseList(key,(List<Object>) obj,parent);
//            } else {
//                if (include(key,obj,parent)){
//                    result = obj;
//                }
//            }
//            return result;
//        }

        /**
         * 遍历List，返回List中所有不为null的元素
         *
         *
         * @param key
         * @param list
         * @param parent
         * @return
         */
//        private List<Object> traverseList(final String key, final List<Object> list, final Map<String, Object> parent) {
//            final List<Object> rl = new ArrayList<Object>();
//            for (final Object value : list) {
//                final Object rs = traverseObject(key,value,parent);
//                if (null != rs) {
//                    rl.add(rs);
//                }
//            }
//            return rl;
//        }
    }
}
